#include "Kernel.h"
#include "Utils/DoubleLinkLinkedList.h"


CLinkedListNode::CLinkedListNode()
{
#if PARANOID
	fSignature = LINKEDLISTNODE_SIGNATURE;
#endif

	fPrev = fNext = NULL;
}


CLinkedList::CLinkedList()
{
#if PARANOID
	fSignature = LINKEDLIST_SIGNATURE;
#endif

	fFirst = fLast = NULL;
	fCount = 0;
}


CLinkedList::~CLinkedList()
{
	fFirst = fLast = NULL;
	fCount = 0;
}


Result CLinkedList::Add( CLinkedListNode * node )
{
	PARANOID_ASSERT( fSignature == LINKEDLIST_SIGNATURE );

	if( node == NULL )
		return ERROR_NULL_PARAM;

	PARANOID_ASSERT( node->fSignature == LINKEDLISTNODE_SIGNATURE );

	node->fPrev = fLast;
	node->fNext = NULL;

	if( fFirst == NULL )
		fFirst = node;

	if( fLast != NULL )
		fLast->fNext = node;

	fLast = node;

	fCount++;
	return RESULT_OK;
}


Result CLinkedList::Insert( CLinkedListNode * node, CLinkedListNode * before )
{
	PARANOID_ASSERT( fSignature == LINKEDLIST_SIGNATURE );

	if( node == NULL )
		return ERROR_NULL_PARAM;

	PARANOID_ASSERT( node->fSignature == LINKEDLISTNODE_SIGNATURE );

	if( before == NULL )
		return Add( node );

	node->fNext = before;

	if( before->fPrev != NULL )
	{
		before->fPrev->fNext = node;
		node->fPrev = before->fPrev;
	}
	else
		node->fPrev = NULL;

	before->fPrev = node;

	if( fFirst == NULL || fFirst == before )
		fFirst = node;

	if( fLast == NULL )
		fLast = node;

	fCount++;
	return RESULT_OK;
}


Result CLinkedList::Remove( CLinkedListNode * node )
{
	PARANOID_ASSERT( fSignature == LINKEDLIST_SIGNATURE );

	if( node == NULL )
		return ERROR_NULL_PARAM;

	PARANOID_ASSERT( node->fSignature == LINKEDLISTNODE_SIGNATURE );

	if( node->fPrev != NULL )
		node->fPrev->fNext = node->fNext;

	if( node->fNext != NULL )
		node->fNext->fPrev = node->fPrev;

	if( fFirst == node )
		fFirst = node->fNext;

	if( fLast == node )
		fLast = node->fPrev;

	fCount--;

	return RESULT_OK;
}
